import json

from django.shortcuts import redirect
from rest_framework import status, viewsets, mixins
from rest_framework_jwt.views import JSONWebTokenAPIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import SessionAuthentication
from core.tools.SerializerAPIView import SerializerAPIView
from .serializers import PaySerializers, MyLoginSerializer, CoffeeOrderSerializer
from apps.czb.models import Orders as CzbOrders
from .models import TLPayRecord, TLRefundRecord
from .client import get_TLClient
from core.tools.get_datetime import GetDateTime
from core.tools.func_utils import parse_qsl
from finance_c2c.local_settings import TLPayResultNoticeUrl
from apps.supply_order.models import SupplyOrder, WomaiChildOrder, PostRecord
from django.http import JsonResponse, HttpResponse
from core.tools.func_utils import funcUtils
from apps.coffee.models import CoffeeOrder
from core.tl.models import AllinPayOrder, AllinPayUnifiedOrder
from core.tl.allinpay import AllinPay



# 获取通联支付链接
class TlPayAPIView(SerializerAPIView):
    """
    获取通联支付链接
        post: 获取支付链接
    """
    permission_classes = (IsAuthenticated,)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    serializer_class = PaySerializers

    def post(self, request):
        user = request.user
        user_id = user.id
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            pay_order_model = serializer.validated_data.get("pay_order_model")
            s_order_pk = serializer.validated_data.get("supply_id")
            pickupUrl = serializer.validated_data.get("redirect_url")
            channel_key = serializer.validated_data.get("channel")  # 渠道对应的key
            channel_key = channel_key if channel_key else "youpinhuiyuan"
            if pay_order_model == "czb":
                czb_order_instance = CzbOrders.objects.get(id=s_order_pk)
                # out_trade_no = czb_order_instance.czb_update_out_trade_no()
                czb_order_instance.update_pay_info(out_trade_no=None, pay_type=3)
                out_trade_no = czb_order_instance.out_trade_no
                order_amount = int(czb_order_instance.payment * 100)
                order_amount = str(order_amount)
                ext2 = "czb"
            else:
                s_order = SupplyOrder.objects.get(id=s_order_pk)
                out_trade_no = s_order.update_out_trade_no()
                order_amount = s_order.payment
                ext2 = None
            h5_client = get_TLClient(channel_key)
            order_datetime = GetDateTime.format_datetime()
            TLPayRecord.objects.create_record(out_trade_no, user_id, order_amount, order_datetime, url=pickupUrl,
                                              channel_key=channel_key)
            # url = h5_client.h5pay_api(user.mobile, user.mobile, order_amount, order_datetime, order_no=out_trade_no,
            #                           pickupUrl=TLPayResultNoticeUrl, ext2=ext2, receiveUrl=TLPayResultNoticeUrl)
            url = h5_client.h5pay_api(user.id, user.mobile, order_amount, order_datetime, order_no=out_trade_no,
                                      pickupUrl=TLPayResultNoticeUrl, ext2=ext2, receiveUrl=TLPayResultNoticeUrl)
            response = {"mweb_url": url}
            print(response, "tl mweb_url")
            return Response(response, status=status.HTTP_200_OK)


# 接收通联钱包付款异步/同步通知
def receive_tl_pay(request):
    print(request.body, "tong lian pay notice body")
    print(request.POST, "tong lian pay notice post")
    print(request.GET, "tong lian pay notice GET")
    print("tong lian pay notice type %s" % request.method)
    body = request.body
    request_params = body.decode()
    params = parse_qsl(request_params, keep_blank_values=True)
    params_dict = {key[0]: key[1] for key in params}
    print(params_dict, "tong lian pay notice")
    sorted_list = ["merchantId", "version", "paymentOrderId", "orderNo", "orderDatetime", "orderAmount",
                   "payDatetime",
                   "payAmount", "ext1", "ext2", "payResult", "errorCode", "returnDatetime"]
    sign_msg = params_dict.pop("signMsg")
    payAmount = params_dict.get("payAmount")
    ext2 = params_dict.get("ext2")
    out_trade_no = params_dict.get("orderNo")
    tl_pay_obj = TLPayRecord.objects.get(orderNo=out_trade_no)
    if ext2 == "czb":
        czb_order_instance = CzbOrders.objects.get(out_trade_no=out_trade_no)
        channel_key = czb_order_instance.channel.app_key
        h5_client = get_TLClient(channel_key)
        source_string = h5_client.sign_msg_stored(params_dict, sorted_list)
        verify_result = h5_client.to_verify_with_public_key(sign_msg, source_string)
        if not verify_result:
            raise Exception("加油，支付通知验签不通过")
        pickup_url = tl_pay_obj.url
        if czb_order_instance.result == 1:  # 支付成功、已经支付
            print('already payment')
            return redirect(pickup_url)
        if int(payAmount) != int(czb_order_instance.payment * 100):
            re = {"return_code": "ERROR", "return_msg": "价格不一致"}
            return Response(re, status=status.HTTP_200_OK)
        czb_order_instance.update_pay_result(1, pay_type=3)  # 1:支付成功
        czb_order_instance.save()
    else:
        h5_client = get_TLClient()
        source_string = h5_client.sign_msg_stored(params_dict, sorted_list)
        verify_result = h5_client.to_verify_with_public_key(sign_msg, source_string)
        if not verify_result:
            raise Exception("购物，支付通知验签不通过")
        s_order = SupplyOrder.objects.get(out_trade_no=out_trade_no)
        pickup_url = tl_pay_obj.url
        if s_order.wx_pay_type != 0:
            return redirect(pickup_url)
        s_order.update_trade_type_fixed(pay_type=3)  # 更新订单
        WomaiChildOrder.objects.update_pay_result(s_order, pay_type="tl")  # 通过支付结果更新其他数据
    pay_record_obj = TLPayRecord.objects.get(orderNo=out_trade_no)
    # 更新通联支付记录
    pay_record_obj.update_record(params_dict.get("paymentOrderId"), True, params_dict.get("payDatetime"),
                                 payAmount)
    return redirect(pay_record_obj.url)


# 再次退款
def refund_again(request):
    channel_key = request.GET.get("channel")
    order_no = request.GET.get("order")
    pay_record = TLPayRecord.objects.get(orderNo=order_no)
    refund_instance = pay_record.tlrefundrecord_set.order_by("-id").first()
    refund_amount = refund_instance.refundAmount
    h5_client = get_TLClient(channel_key)
    out_refund_no = funcUtils.unique_value  # 退款订单号(新生成的)
    status, message = TLRefundRecord.objects.tl_refund(refund_amount, order_no, pay_record, out_refund_no,
                                                       channel_key=channel_key)
    response = {"status": status, "message": message}
    response_search = h5_client.refund_search(refund_amount, order_no)
    response["response_search"] = response_search
    return JsonResponse(response)


# 再次查询(更新)
def search_again(request):
    channel_key = request.GET.get("channel") if request.GET.get("channel") else None
    order_no = request.GET.get("order")
    pay_record = TLPayRecord.objects.get(orderNo=order_no)
    refund_instance = pay_record.tlrefundrecord_set.order_by("-id").first()
    refund_amount = refund_instance.refundAmount
    status, message = TLRefundRecord.objects.tl_refund_search(refund_amount, order_no, pay_record,
                                                              channel_key=channel_key)
    return JsonResponse({"status": status, "message": message})


# 通联联合登录
class TLLoginRegisterViewSet(JSONWebTokenAPIView):
    serializer_class = MyLoginSerializer


def payment_notice(request):
    """
    通联小程序支付通知接口
    """
    data = request.POST
    mchOrderNo = data.get("mchOrderNo")
    amount = data.get("amount")
    order_instance = CoffeeOrder.objects.get(orderNo=mchOrderNo) # 咖啡机订单号
    pay_type = 97
    allinPay = AllinPay()
    query_dict_dict = data.dict()
    print(query_dict_dict, "yun wei pay notice post  form data")
    if allinPay.validate_sign(query_dict_dict):
        AllinPayOrder.objects.create_order(
            data
        )
        order_instance.update_result(pay_type=pay_type, total_fee=amount)  # 更新云微订单
        return HttpResponse("success")
    else:
        return HttpResponse("error")


def refund_notice(request):
    """
    通联小程序支付通知接口
    """
    data = request.POST
    query_dict_dict = data.dict()
    print(query_dict_dict, "yun wei refund notice post  form data")
    mchRefundNo = data.get("mchRefundNo")
    refund_instance = AllinPayUnifiedOrder.objects.get(mchRefundNo=mchRefundNo) # 商户退款订单号
    state = data.get("state")
    if state == 2 or state == "2":
        successTime = data.get("successTime")
        refundAmount = data.get("refundAmount")
        refundOrderId = data.get("refundOrderId")
        orderNo = data.get("extParam")
        # {'payOrderId': 'P1935253341832806401', 'extParam': '202506171458503495097889',
        # 'sign': 'A4DD7D373434D1F591B828857EA5F3FD', 'channelOrderNo': '732506181652334883678',
        # 'reqTime': '1750236981512', 'refundOrderId': 'R1935259324787105794', 'createdAt': '1750236753065',
        # 'payAmount': '1', 'appId': '68073139e4b01550865a9e39', 'mchRefundNo': '1750236740604138594',
        # 'successTime': '1750236981000', 'signType': 'MD5', 'currency': 'cny', 'state': '2',
        # 'channelPayOrderNo': '732506181628467471428', 'mchNo': 'E259974077640', 'refundAmount': '1'}
        refund_instance.update_state(state, successTime, refundAmount, refundOrderId)  # 云微退款记录
        # 更新自己订单的退款记录
        from apps.supply_order.models import RefundRecord
        data = {"refund_fee": refundAmount, "refund_type": 4, "out_refund_no": mchRefundNo}
        self_refund_instance = RefundRecord.objects.create_refund(**data)
        from apps.coffee.models import CoffeeOrder
        order_instance = CoffeeOrder.objects.get(orderNo=orderNo)
        order_instance.refund_coupon(result=2, refund=self_refund_instance)
        return HttpResponse("success")
    else:
        return HttpResponse("error")



class AllinPayViewSets(mixins.UpdateModelMixin, viewsets.GenericViewSet):
    permission_classes = (IsAuthenticated,)
    authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
    serializer_class = CoffeeOrderSerializer
    lookup_field = "orderNo"

    def get_queryset(self):
        from apps.coffee.models import CoffeeOrder
        return CoffeeOrder.objects.all()

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}
        allinPay = AllinPay()
        content = allinPay.unifiedOrder(instance.orderNo, instance.payment)
        print("tl pay ", content.content)
        data = json.loads(content.content)
        print(data)
        return Response(data)
